package cn.kinoko.service.common.export.component;

import cn.kinoko.service.common.export.ExportHandler;
import cn.kinoko.service.common.export.ExportTopic;
import cn.kinoko.service.common.export.ExportTopicEnum;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author kk
 */
@Slf4j
@Component
public class ExportHandlerClassLoader implements ApplicationContextAware {

    private final Map<Integer, ExportHandler> exportHandlerMap = Maps.newHashMap();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("[导出处理类加载器]正在加载导出处理类...");
        // 从上下文中获取带有@Topic注解的事件处理类
        Map<String, Object> topicAnnotatedBeans = applicationContext.getBeansWithAnnotation(ExportTopic.class);
        // 放入Map中，以Topic的事件类型为key，处理类为value
        for (Object handler : topicAnnotatedBeans.values()) {
            // 判断是否实现了ExportHandler接口
            if (!ExportHandler.class.isAssignableFrom(handler.getClass())) {
                continue;
            }
            // 获取类上的主题事件类型
            ExportTopic topicAnnotation = AnnotationUtils.findAnnotation(handler.getClass(), ExportTopic.class);
            if (topicAnnotation != null) {
                ExportTopicEnum[] topics = topicAnnotation.value();
                // 放入加载器map
                for (ExportTopicEnum topic : topics) {
                    exportHandlerMap.put(topic.getCode(), (ExportHandler) handler);
                    log.info("[导出处理类加载器]已加载：[{}]{} => {}", topic.getCode(), topic.getDesc(), handler.getClass().getSimpleName());
                }
            }
        }
    }

    @Bean
    public Map<Integer, ExportHandler> getExportHandlerMap() {
        return exportHandlerMap;
    }
}
